function varargout = soundtrack(varargin)
% SOUNDTRACK M-file for soundtrack.fig
%      SOUNDTRACK, by itself, creates a new SOUNDTRACK or raises the existing
%      singleton*.
%
%      SOUNDTRACK = SOUNDTRACK returns the handle to a new SOUNDTRACK or the handle to
%      the existing singleton*.
%
%      SOUNDTRACK('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in SOUNDTRACK.M with the given input arguments.
%
%      SOUNDTRACK('Property','Value',...) creates a new SOUNDTRACK or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before soundtrack_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to soundtrack_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help soundtrack

% Last Modified by GUIDE v2.5 24-May-2012 09:58:23

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @soundtrack_OpeningFcn, ...
                   'gui_OutputFcn',  @soundtrack_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before soundtrack is made visible.
function soundtrack_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to soundtrack (see VARARGIN)

% Choose default command line output for soundtrack.
handles.output = hObject;
% Set the version number. (This, I believe, is the only place that has to
% be modified in order to change the version number everywhere, including
% the name of the executable and the GUI windows title.)
versionStr = '0.3';

% Set the GUI name to appear in the window title.
set(hObject, 'Name', ['AEO-Light v' versionStr]);

img = usclogo();
set(handles.logo,'CData',img);
set(handles.logo,'Units','Pixels');
pos = get(handles.logo,'Position');
pos(3) = size(img,2) + 8;
pos(4) = size(img,1) + 8;
set(handles.logo, 'Position', pos);

% Set the name of the file where the copyright acceptance and user
% preferences are to be stored.
if(isunix)
    handles.userfile = '~/.aeo_light';
else
    handles.userfile = [getenv('UserProfile') filesep 'aeo_light.cfg'];
end

handles.scratch_default_string = '';

% Update handles structure.
guidata(hObject, handles);


% Check if the copyright has been already accepted (i.e., if a copyright
% acceptance file exists and has the appropriate copyright acceptance for
% the current version).
userAgreementText = ['Accept Copyright ' versionStr];

tokExpr = '(?<tok>\w+)\s+(?<val>.*\S)';
fid = fopen(handles.userfile, 'r');
if (fid == -1)
    ask = 1;
else
    uline = fgetl(fid);
    ask = 1;
    while ischar(uline)
        if (strfind(uline, userAgreementText))
            ask = 0;
        else
           m = regexp(uline, tokExpr, 'names');
           if(~isempty(m))
               switch lower(m.tok)
                   case 'scratch'
                       set(handles.scratch_directory,'String',m.val);
                       handles.scratch_default_string = m.val;
                       guidata(hObject, handles);
                       createMissingDirs(m.val);
               end
           end
        end
        uline = fgetl(fid);
    end
    fclose(fid);
end

% If there is no proof that copyright has been accepted, then ask for
% acceptance now.
if(ask)
    button = questdlg({...
        'Copyright (c) 2012, South Carolina Research Foundation',...
        'All Rights Reserved',...
        ['AEO-Light, Ver. ' versionStr ' (Alpha)'],...
        '',...
        'This is alpha software. See the Readme file for full disclaimer. ',...
        'Press [Agree] if you agree to the terms in the Readme file.'},...
        'AEO-Light', 'Exit', 'Agree', 'Exit');

    if(strcmp(button,'Agree'))
        fid = fopen(handles.userfile, 'a');
        if(fid ~= -1)
            fprintf(fid,'%s\n',userAgreementText);
            fclose(fid);
        end
    else
        quit;
    end
end
%waitfor(f);

% UIWAIT makes soundtrack wait for user response (see UIRESUME)
%uiwait(handles.soundtrack);

function update_pref(preffile, token, value)

tokExpr = '(?<tok>\w+)\s+(?<val>.*\S)';
fid = fopen(preffile, 'r+');
if (fid > 0)
    pos = ftell(fid);
    uline = fgetl(fid);
    done = 0;
    while(ischar(uline) && done==0)
       m = regexp(uline, tokExpr, 'names');
       if(~isempty(m))
           switch lower(m.tok)
               case 'scratch'
                   remainder = fread(fid);
                   fseek(fid,pos,'bof');
                   done = 1;
           end
       end
       if(done==0)
           uline = fgetl(fid);
       end
    end
    if(done == 0)
        fseek(fid, 0, 'eof');
    end
    fprintf(fid, '%s %s\n', token, value);
    if(done == 1)
        fwrite(fid,remainder);
    end
    fclose(fid);
end


% --- Outputs from this function are returned to the command line.
function varargout = soundtrack_OutputFcn(hObject, eventdata, handles) 
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;


% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --- Executes on slider movement.
function slider1_Callback(hObject, eventdata, handles)
% hObject    handle to slider1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'Value') returns position of slider
%        get(hObject,'Min') and get(hObject,'Max') to determine range of slider


% --- Executes during object creation, after setting all properties.
function slider1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to slider1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end



function edit1_Callback(hObject, eventdata, handles)
% hObject    handle to edit1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit1 as text
%        str2double(get(hObject,'String')) returns contents of edit1 as a double


% --- Executes during object creation, after setting all properties.
function edit1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


% --------------------------------------------------------------------
function menu_file_Callback(hObject, eventdata, handles)
% hObject    handle to menu_file (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function menu_file_open_Callback(hObject, eventdata, handles)
% hObject    handle to menu_file_open (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)



function directory_Callback(hObject, eventdata, handles)
% hObject    handle to directory (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of directory as text
%        str2double(get(hObject,'String')) returns contents of directory as a double


% --- Executes during object creation, after setting all properties.
function directory_CreateFcn(hObject, eventdata, handles)
% hObject    handle to directory (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


function input_directory_Callback(hObject, eventdata, handles)
% hObject    handle to input_directory (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of input_directory as text
%        str2double(get(hObject,'String')) returns contents of input_directory as a double
inDir = get(hObject,'String');
frame_start = 0;
frame_end = Inf;
loadfile(hObject, handles, inDir, frame_start, frame_end);
set(handles.extract_button, 'Enable', 'off');
set(handles.play_button, 'Enable', 'off');




% --- Executes during object creation, after setting all properties.
function input_directory_CreateFcn(hObject, eventdata, handles)
% hObject    handle to input_directory (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function output_directory_Callback(hObject, eventdata, handles)
% hObject    handle to output_directory (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of output_directory as text
%        str2double(get(hObject,'String')) returns contents of output_directory as a double


% --- Executes during object creation, after setting all properties.
function output_directory_CreateFcn(hObject, eventdata, handles)
% hObject    handle to output_directory (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


% --- Executes on button press in browse_output.
function browse_output_Callback(hObject, eventdata, handles)
% hObject    handle to browse_output (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
dirname = uigetdir(get(hObject,'String'),'Output (Target) Directory');
if isequal(dirname, 0)
    return
else
    % Add a file separator (i.e., \ for Windows or / for Linux) at the end
    % of the directory name in case it does not have one.
    if (strcmpi(dirname(end), filesep) == false)
        dirname = [dirname filesep];
    end
    set(handles.output_directory,'String',dirname);
end 


function frame_start_Callback(hObject, eventdata, handles)
% hObject    handle to frame_start (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of frame_start as text
%        str2double(get(hObject,'String')) returns contents of frame_start as a double
cur_start = sscanf(get(hObject, 'String'),'%lu');
if cur_start > handles.fileIdxArr(end);
    cur_end = sscanf(get(handles.frame_end,'String'),'%lu');
    if isnan(cur_end)
        cur_end = Inf;
    end
    inDir = get(handles.input_directory,'String');
    frame_start = 0;
    frame_end = Inf;
    loadfile(hObject, handles, inDir, frame_start, frame_end);
    handles = guidata(hObject);
    handles.frame_min = handles.fileIdxArr(1);
    handles.frame_max = handles.fileIdxArr(end);
    set(handles.frame_end,'String',cur_end);
    guidata(hObject,handles);
    
    if cur_start > handles.frame_max
        h = errordlg('Frame index out of range. Setting to last frame.',...
            'Index Error','modal');
        set(hObject, 'String', handles.frame_max);
    else
        set(hObject, 'String', cur_start);        
    end
end
    

% --- Executes during object creation, after setting all properties.
function frame_start_CreateFcn(hObject, eventdata, handles)
% hObject    handle to frame_start (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function frame_end_Callback(hObject, eventdata, handles)
% hObject    handle to frame_end (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of frame_end as text
%        str2double(get(hObject,'String')) returns contents of frame_end as a double
cur_end = sscanf(get(hObject, 'String'),'%lu');
if cur_end < handles.fileIdxArr(1);
    cur_start = sscanf(get(handles.frame_start,'String'),'%lu');
    if isnan(cur_start)
        cur_start = 0;
    end
    inDir = get(handles.input_directory,'String');
    frame_start = 0;
    frame_end = Inf;
    loadfile(hObject, handles, inDir, frame_start, frame_end);
    handles = guidata(hObject);
    handles.frame_min = handles.fileIdxArr(1);
    handles.frame_max = handles.fileIdxArr(end);
    set(handles.frame_end,'String',cur_start);
    guidata(hObject,handles);
    
    if cur_end < handles.frame_min
        h = errordlg('Frame index out of range. Setting to first frame.',...
            'Index Error','modal');
        set(hObject, 'String', handles.frame_min);
    else
        set(hObject, 'String', cur_end);        
    end
end


% --- Executes during object creation, after setting all properties.
function frame_end_CreateFcn(hObject, eventdata, handles)
% hObject    handle to frame_end (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function scratch_directory_Callback(hObject, eventdata, handles)
% hObject    handle to scratch_directory (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of scratch_directory as text
%        str2double(get(hObject,'String')) returns contents of scratch_directory as a double

dirname = get(hObject,'String');
if (strcmpi(dirname(end), filesep) == false)
        dirname = [dirname filesep];
        set(hObject, 'String', dirname);
end
createMissingDirs(dirname);
    

% --- Executes during object creation, after setting all properties.
function scratch_directory_CreateFcn(hObject, eventdata, handles)
% hObject    handle to scratch_directory (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


% --- Executes on button press in locate_button.
function locate_button_Callback(hObject, eventdata, handles)
% hObject    handle to locate_button (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
inDir = get(handles.input_directory,'String');

[frame_start, frame_end] = getBoundsFromGui(handles);

ret = loadfile(hObject, handles, inDir, frame_start, frame_end);

if(ret == 0)
    return
end

% Get the new data reflecting all modifications that may have occured
% inside the function "loadfile".
handles = guidata(hObject);

inDirPath = handles.inDirPath;
inFilePrefix = handles.inFilePrefix;
fileIdxArr = handles.fileIdxArr;

numTestFiles = 5;
[left, right] = getSoundTrackBounds([inDirPath inFilePrefix], ...
   fileIdxArr, numTestFiles, handles.idxFieldLen, handles.inFileExt);

set(handles.extract_button, 'Enable', 'on');


handles.leftBound = left;
handles.rightBound = right;
guidata(hObject,handles);


% --- Executes on button press in extract_button.
function extract_button_Callback(hObject, eventdata, handles)
% hObject    handle to extract_button (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

set(handles.play_button, 'Enable', 'off');

idx = get(handles.soundSep,'Value');
string_list = get(handles.soundSep,'String');
audioDelay = sscanf(string_list{idx}, '%d ');

inDir = get(handles.input_directory,'String');
[frame_start, frame_end] = getBoundsFromGui(handles);
ret = loadfile(hObject, handles, inDir, frame_start, frame_end);

if(ret == 0)
    return
end
 
% Get the new data reflecting all modifications that may have occured
% inside the function "loadfile".
handles = guidata(hObject);


% BK: Not sure if this waitbar is needed any longer.
% h = waitbar(0, 'Extracting audio...');
% set(findobj(h,'type','patch'), ...
% 'edgecolor','k','facecolor','b')


% Create a string expressing the range of file indices.
imageRangeStr = ['Im' num2str(handles.fileIdxArr(1)) '-' ...
    num2str(handles.fileIdxArr(end)) '_'];
% Create a string expressing the soundtrack's vertical bounds.
soundBoundsStr = ['SndBnds' num2str(handles.leftBound) '-' ...
    num2str(handles.rightBound)];

% Construct the name of the output directory.
if isempty(get(handles.output_directory, 'String'))
    outBase = get(handles.input_directory, 'String');
else
    outBase = get(handles.output_directory, 'String');
end

handles.outDirPath = generateOutputDirectory(outBase, ...
    [handles.inFilePrefix imageRangeStr soundBoundsStr]);
%set(handles.output_directory, 'String', handles.outDirPath);
    
% Create the output directory unless it already exists.
createMissingDirs(handles.outDirPath);
% Save the output directory.
guidata(hObject, handles);

origDir = cd(handles.outDirPath);
origPath = path;
path(origPath, origDir);

try
   

% Define and set the global variables pertaining to the names of any output
% files that might be created during execution.
doVisualize = false;
doLog = true;
setGlobalVariables(doVisualize, doLog, handles.outDirPath, ...
    handles.inFilePrefix, 'bmp');

global globalShotFileNamePrefix
if (isempty(globalShotFileNamePrefix) == false)
    % Reflect the knowledge of the range of file indices and the soundtrack
    % boundaries in the prefix of the names of the image files saving
    % snapshots of figures.
    globalShotFileNamePrefix = ...
        [globalShotFileNamePrefix imageRangeStr soundBoundsStr '_'];
end


% Get the scratch directory.
scratchDirPath = get(handles.scratch_directory, 'String');

% Start timing.
timeStart = tic;

% Extract the sound.
[audioFile, videoFileNameCellArr] = extractForGUI(handles.inDirPath, ...
    handles.inFilePrefix, handles.outDirPath, ...
    scratchDirPath, handles.idxFieldLen, handles.inFileExt, ...
    handles.fileIdxArr, handles.leftBound, handles.rightBound, audioDelay);

if isempty(audioFile) || isempty(videoFileNameCellArr)
    cd(origDir);
    path(origPath);
    return;
end
% End timing.
timeElapsed = toc(timeStart);


secPerFrame = timeElapsed/numel(handles.fileIdxArr);
msgbox({['Sound reconstruction ran at ' ...
    num2str(secPerFrame, '%.1f') ' seconds per frame,'], ...
    ['i.e., at ' num2str(60/secPerFrame, '%.1f') ' frames per minute.']});


handles.audioFile = audioFile;
handles.movieFile = videoFileNameCellArr{end};
guidata(hObject, handles);

% BK: Not sure if this waitbar is needed any longer. By the way, I think I
% read somewhere that waitbars are better terminated with delete() rather
% than with close(). Not sure is that applies in this case.
% close(h);

% LSJ: Some need to be delete()ed. But not simple ones like this (was).

set(handles.play_button, 'Enable', 'on');

cd(origDir);
path(origPath);

catch exception
	getReport(exception, 'extended', 'hyperlinks', 'on');
	errordlg(exception.message, 'Error', 'modal')
	ret = 0;
    cd(origDir);
    path(origPath);
	return
end


% --------------------------------------------------------------------
function menu_file_new_Callback(hObject, eventdata, handles)
% hObject    handle to menu_file_new (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function menu_file_save_Callback(hObject, eventdata, handles)
% hObject    handle to menu_file_save (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function menu_file_quit_Callback(hObject, eventdata, handles)
% hObject    handle to menu_file_quit (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --- Executes on slider movement.
function thumbnail_slider_Callback(hObject, eventdata, handles)
% hObject    handle to thumbnail_slider (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'Value') returns position of slider
%        get(hObject,'Min') and get(hObject,'Max') to determine range of slider

idx = uint32(get(hObject, 'value'));
% frame = handles.fileIdxArr(idx);

% Read in the specified image.
doConvertToGray = false;
[imageArr, bitDepth] = readImageByIndex(handles.fileIdxArr(idx), ...
    [handles.inDirPath handles.inFilePrefix], handles.idxFieldLen, handles.inFileExt, doConvertToGray);
% Scale pixel values in case they are integers.
if (isinteger(imageArr) == true)
    % Compute the number of bits used to store each pixel value.
    storageBitDepth = round(log2(double(intmax(class(imageArr)))));
    
    % Check if the type used to store the pixel values can accomodate them.
    assert((storageBitDepth >= bitDepth), 'SoundRestoration:soundtrack:TooSmallStorageType', ...
        'Type used to store the pixel values is too small to accomodate them');
    
    % Scale pixel values to the full range offered by the type used to 
    % store them.
    scale = 2^(storageBitDepth - bitDepth);
    imageArr = imageArr*scale;
end
imshow(imageArr);
% end of the function "thumbnail_slider_Callback"


% --- Executes during object creation, after setting all properties.
function thumbnail_slider_CreateFcn(hObject, eventdata, handles)
% hObject    handle to thumbnail_slider (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end


% --- Executes on button press in browse.
function browse_Callback(hObject, eventdata, handles)
% hObject    handle to browse (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
dirname = uigetdir(get(hObject,'String'),'Input (Source) Directory');
if isequal(dirname, 0)
    return
else
    % Add a file separator (i.e., \ for Windows or / for Linux) at the end
    % of the directory name in case it does not have one.
    if (strcmpi(dirname(end), filesep) == false)
        dirname = [dirname filesep];
    end
    set(handles.input_directory,'String',dirname);

    frame_start = 0;
    frame_end = Inf;
    loadfile(hObject, handles, dirname, frame_start, frame_end);
    handles = guidata(hObject);
    
    handles.frame_min = handles.fileIdxArr(1);
    handles.frame_max = handles.fileIdxArr(end);
    guidata(hObject,handles);
end 
% 
% [input_directory, pathname, filterIdx] = uigetfile(['.' filesep '*.dpx']);
% if isequal(input_directory, 0)
%     return
% else
%     set(handles.input_directory,'String',[pathname input_directory]);
% end
    

% --- Executes on selection change in soundSep.
function soundSep_Callback(hObject, eventdata, handles)
% hObject    handle to soundSep (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns soundSep contents as cell array
%        contents{get(hObject,'Value')} returns selected item from soundSep

string_list = cellstr(get(hObject, 'String'));
idx = get(hObject, 'Value');
sel = string_list{idx};
if isequal(sel, 'Custom ...')
    answer = inputdlg('Custom sound separtion value:');
    if length(answer)
        string_list{idx+1} = string_list{idx};
        string_list{idx} = answer{1};
        set(hObject,'String',string_list);
    else
        set(hObject,'Value',idx-1);
    end
end

% --- Executes during object creation, after setting all properties.
function soundSep_CreateFcn(hObject, eventdata, handles)
% hObject    handle to soundSep (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


% --- Executes on button press in browse_scratch.
function browse_scratch_Callback(hObject, eventdata, handles)
% hObject    handle to browse_scratch (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
dirname = uigetdir(get(hObject,'String'),'Scratch directory');
if isequal(dirname, 0)
    return
else
    % Add a file separator (i.e., \ for Windows or / for Linux) at the end
    % of the directory name in case it does not have one.
    if (strcmpi(dirname(end), filesep) == false)
        dirname = [dirname filesep];
    end
    set(handles.scratch_directory,'String',dirname);
end
createMissingDirs(dirname);


function ret = loadfile(hObject, handles, inDir, frame_start, frame_end)
%
ret = 1;

try
    % Find all files in the input directory and their number.
    fileListing = dir(inDir);
    numFiles = numel(fileListing);

    template = '0';
    % Find the indices of all files residing in the input directory that have
    % the same prefix and extension as the given input file name.
    for k = 1:numFiles
        if(regexpi(fileListing(k).name,'\.dpx$'))
            template = [inDir fileListing(k).name];
            break
        end
    end
    
    if(template == '0')
        errordlg('No DPX files found.', 'Error', 'modal')
        ret = 0;
        return
    end
    
    h = waitbar(0.1,'Reading frames...');
    [inDirPath, inFilePrefix, idxFieldLen, inFileExt, fileIdxArr] = ...
        getFileSequenceFromRepresetative(template, frame_start, frame_end);
    close(h);
catch exception
    %if isequal('SoundRestoration:GapsInFileSequence', exception.identifier)
        %warndlg(exception.message, 'Warning', 'modal')
    %else
        getReport(exception, 'extended', 'hyperlinks', 'on');
        errordlg(exception.message, 'Error', 'modal')
        ret = 0;
        return
    %end
end

handles.inDirPath = inDirPath;
handles.inFilePrefix = inFilePrefix;
handles.idxFieldLen = idxFieldLen;
handles.inFileExt = inFileExt;
handles.fileIdxArr = fileIdxArr;

if isempty(get(handles.output_directory, 'String'))
    outDir = inDir;
    set(handles.output_directory, 'String', outDir);
end

guidata(hObject,handles);

set(handles.frame_start, 'Enable', 'on');
set(handles.frame_end, 'Enable', 'on');
set(handles.frame_label, 'Enable', 'on');
set(handles.soundSep, 'Enable', 'on');
set(handles.soundSep_label, 'Enable', 'on');
set(handles.thumbnail_slider, 'Enable', 'on');
set(handles.locate_button, 'Enable', 'on');

set(handles.frame_start,'String',sprintf('%lu',fileIdxArr(1)));
set(handles.frame_end,'String',sprintf('%lu',fileIdxArr(end)));

set(handles.thumbnail_slider, 'Min', 1);
set(handles.thumbnail_slider, 'Max', length(fileIdxArr));
set(handles.thumbnail_slider, 'Value', 1);
thumbnail_slider_Callback(handles.thumbnail_slider, '', handles);



function [frame_start, frame_end] = getBoundsFromGui(handles)

frame_start = sscanf(get(handles.frame_start,'String'),'%lu');
if isnan(frame_start) || (frame_start < 0)
    frame_start = 0;
end
frame_end = sscanf(get(handles.frame_end,'String'),'%lu');
if isnan(frame_end)
    frame_end = Inf;
elseif frame_end < frame_start
    frame_end = frame_start;
end



% --- Executes on button press in logo.
function logo_Callback(hObject, eventdata, handles)
% hObject    handle to logo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --- Executes on button press in play_button.
function play_button_Callback(hObject, eventdata, handles)
% hObject    handle to play_button (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    playMovie(handles.movieFile)
catch exception
    getReport(exception, 'extended', 'hyperlinks', 'on');
    errordlg(exception.message, 'Error', 'modal')
    ret = 0;
    return
end




% --- Executes during object creation, after setting all properties.
function logo_CreateFcn(hObject, eventdata, handles)
% hObject    handle to logo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called


% --- Executes on button press in reset_button.
function reset_button_Callback(hObject, eventdata, handles)
% hObject    handle to reset_button (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

set(handles.input_directory, 'String', '');
set(handles.output_directory, 'String', '');
set(handles.scratch_directory, 'String', handles.scratch_default_string);

set(handles.frame_start, 'Enable', 'off');
set(handles.frame_end, 'Enable', 'off');
set(handles.frame_label, 'Enable', 'off');
set(handles.soundSep, 'Enable', 'off');
set(handles.soundSep_label, 'Enable', 'off');
set(handles.thumbnail_slider, 'Enable', 'off');
set(handles.locate_button, 'Enable', 'off');
set(handles.extract_button, 'Enable', 'off');
set(handles.play_button, 'Enable', 'off');
set(handles.frame_start,'String','1');
set(handles.frame_end,'String','');

set(handles.thumbnail_slider, 'Min', 0);
set(handles.thumbnail_slider, 'Max', 1);
set(handles.thumbnail_slider, 'Value', 0);
reset(handles.thumbnail);
whitepix(1,1,1) = 1;
whitepix(1,1,2) = 1;
whitepix(1,1,3) = 1;
imshow(whitepix, [0, 1]);


% --------------------------------------------------------------------
function menu_help_Callback(hObject, eventdata, handles)
% hObject    handle to menu_help (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function menu_help_about_Callback(hObject, eventdata, handles)
% hObject    handle to menu_help_about (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

h = msgbox({...
    ['AEO-Light is a collaborative project of the University '...
    'of South Carolina''s Moving Image Research Collections (MIRC) '...
    'and Interdisciplinary Mathematics Institute (IMI) '...
    'funded by the generous support of the National Endowment '...
    'for the Humanities.  Visit the project website for details.']
    }, 'About AEO-Light','modal');


% --------------------------------------------------------------------
function menu_help_web_project_Callback(hObject, eventdata, handles)
% hObject    handle to menu_help_web_project (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
web('http://imi.cas.sc.edu/mirc/','-browser');


% --------------------------------------------------------------------
function menu_help_web_mirc_Callback(hObject, eventdata, handles)
% hObject    handle to menu_help_web_mirc (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
web('http://library.sc.edu/mirc','-browser');


% --------------------------------------------------------------------
function menu_help_web_Callback(hObject, eventdata, handles)
% hObject    handle to menu_help_web (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function menu_help_web_imi_Callback(hObject, eventdata, handles)
% hObject    handle to menu_help_web_imi (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
web('http://imi.cas.sc.edu','-browser');


% --- Executes during object creation, after setting all properties.
function soundtrack_CreateFcn(hObject, eventdata, handles)
% hObject    handle to soundtrack (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called


% --- Executes on button press in mkdefault_scratch.
function mkdefault_scratch_Callback(hObject, eventdata, handles)
% hObject    handle to mkdefault_scratch (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
update_pref(handles.userfile, 'scratch', ...
    get(handles.scratch_directory,'String'));
handles.scratch_default_string = get(handles.scratch_directory,'String');
guidata(hObject, handles);




% --- Executes when soundtrack is resized.
function soundtrack_ResizeFcn(hObject, eventdata, handles)
% hObject    handle to soundtrack (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
